package service

import (
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/elastic/go-elasticsearch/v7/esapi"
	"log"
	"math/rand"
	"strconv"
	"sync"
	"time"
	"video-srv/basic/config"
	__ "video-srv/basic/proto/rpc"
	"video-srv/handler/model"
)

type VideoServer struct {
	__.UnimplementedVideoServer
}

func (s *VideoServer) PublishVideo(_ context.Context, in *__.PublishVideoReq) (*__.PublishVideoResp, error) {
	video := model.Video{
		UserId: int(in.UserId),
		Title:  in.Title,
		Image:  in.Image,
		Tags:   in.Tags,
		Refer:  in.Refer,
	}
	err := video.PublishVideo(config.DB)
	if err != nil {
		return nil, err
	}
	return &__.PublishVideoResp{
		VideoId: int64(video.ID),
	}, nil
}

func (s *VideoServer) CheckVideo(_ context.Context, in *__.CheckVideoReq) (*__.CheckVideoResp, error) {
	video := model.CheckVideo{
		UserId:  int(in.UserId),
		VideoId: int(in.VideoId),
		Reason:  in.Reason,
		Status:  int(in.Status),
	}
	err := video.CheckVideo(config.DB)
	if err != nil {
		return nil, err
	}
	var v model.Video
	err = v.UpdateVideoStatus(config.DB, int(in.VideoId), int(in.Status))
	if err != nil {
		return nil, err
	}
	return &__.CheckVideoResp{
		CheckVideoId: int64(video.ID),
	}, nil
}

func (s *VideoServer) GetVideoListById(_ context.Context, in *__.GetVideoListByIdReq) (*__.GetVideoListByIdResp, error) {
	var video model.Video
	list, err := video.GetVideoListById(config.DB, int(in.UserId), int(in.Page), int(in.Size))
	if err != nil {
		return nil, err
	}
	return &__.GetVideoListByIdResp{
		List: list,
	}, nil
}

func (s *VideoServer) GetVideoList(_ context.Context, in *__.GetVideoListReq) (*__.GetVideoListResp, error) {
	var video model.Video
	list, err := video.GetVideoList(config.DB, in.AreaName, in.CategoryName, in.ChannelName, in.YearName)
	if err != nil {
		return nil, err
	}
	key := fmt.Sprintf("videoList_%d", rand.Intn(100))
	cacheList, _ := config.Rdb.Get(config.Ctx, key).Result()
	if cacheList == "" {
		videoJson, _ := json.Marshal(list)
		config.Rdb.Set(config.Ctx, key, videoJson, time.Hour)
	} else {
		json.Unmarshal([]byte(cacheList), &list)
	}
	var wg sync.WaitGroup
	for _, videoList := range list {
		wg.Add(1)
		go func(videoList *__.VideoList) {
			defer wg.Done()
			data, err := json.Marshal(videoList)
			if err != nil {
				log.Fatalf("Error marshaling document: %s", err)
			}
			req := esapi.IndexRequest{
				Index:      "video_110501",
				DocumentID: strconv.Itoa(int(videoList.Id)),
				Body:       bytes.NewReader(data),
				Refresh:    "true",
			}
			res, err := req.Do(context.Background(), config.Es)
			if err != nil {
				log.Fatalf("Error getting response: %s", err)
			}
			defer res.Body.Close()
		}(videoList)
	}
	wg.Wait()
	return &__.GetVideoListResp{
		List: list,
	}, nil
}

func (s *VideoServer) LookVideo(_ context.Context, in *__.LookVideoReq) (*__.LookVideoResp, error) {
	var user model.User
	err := user.IsUser(config.DB, int(in.UserId))
	if err != nil {
		return nil, err
	}
	var member model.Member
	err = member.IsMember(config.DB, int(in.MemberId))
	if err != nil {
		return nil, err
	}
	var episode model.Episode
	err = episode.GetEpisodeList(config.DB, int(in.VideoId))
	if err != nil {
		return nil, err
	}
	if user.MemberStatus == 0 && episode.IsFree != 0 {
		return nil, errors.New("该视频需要充值会员播放")
	}
	return &__.LookVideoResp{
		VideoUrl: episode.VideoUrl,
	}, nil
}
